/* Read battery voltage

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/

#include "adc_battery.h"

static const char *TAG = "DEZ_BATTERY";

bool adc_init(void *user_data)
{
    gpio_reset_pin(PIN_NUM_BATEN);
    gpio_set_direction(PIN_NUM_BATEN, GPIO_MODE_OUTPUT);
    vol_adc_param_t *adc_cfg = (vol_adc_param_t *)user_data;
    adc1_config_width(adc_cfg->width);
    adc1_config_channel_atten(adc_cfg->chan, adc_cfg->atten);
    return true;
}

bool adc_deinit(void *user_data)
{
    return true;
}

/**
 * @brief  电池采样读取
 */
int vol_read(void *user_data)
{
    // ESP_LOGI(TAG, "trigger read event");
    gpio_set_level(PIN_NUM_BATEN, 1);

#define ADC_SAMPLES_NUM (10)

    vol_adc_param_t *adc_cfg = (vol_adc_param_t *)user_data;

    uint32_t data[ADC_SAMPLES_NUM] = {0};
    uint32_t sum = 0;
    int tmp = 0;

    esp_adc_cal_characteristics_t characteristics;
    esp_adc_cal_characterize(adc_cfg->unit, adc_cfg->atten, adc_cfg->width, adc_cfg->v_ref, &characteristics);

    for (int i = 0; i < ADC_SAMPLES_NUM; ++i)
    {
        esp_adc_cal_get_voltage(adc_cfg->chan, &characteristics, &data[i]);
    }

    for (int j = 0; j < ADC_SAMPLES_NUM - 1; j++)
    {
        for (int i = 0; i < ADC_SAMPLES_NUM - j - 1; i++)
        {
            if (data[i] > data[i + 1])
            {
                tmp = data[i];
                data[i] = data[i + 1];
                data[i + 1] = tmp;
            }
        }
    }
    for (int num = 1; num < ADC_SAMPLES_NUM - 1; num++)
        sum += data[num];
    gpio_set_level(PIN_NUM_BATEN, 0);
    return (int)((sum / (ADC_SAMPLES_NUM - 2)) * adc_cfg->ratio);
}

/**
 * @brief  battery callback 
 */
esp_err_t battery_service_cb(periph_service_handle_t handle, periph_service_event_t *evt, void *ctx)
{
    // ESP_LOGI(TAG, "trigger event");
    if (evt->type == BAT_SERV_EVENT_VOL_REPORT)
    {
        int voltage = (int)evt->data;
        ESP_LOGI(TAG, "got voltage %d", voltage);
        if (voltage <= 3500) //低于3.5V 上报batResult = 1
        {
            QueueHandle_t batteryQueue;
            batteryQueue = (QueueHandle_t)ctx;
            int batResult = 1;
            BaseType_t xStatus;
            xStatus = xQueueSend(batteryQueue, &batResult, 0);
        }
    }
    else if (evt->type == BAT_SERV_EVENT_BAT_FULL)
    {
        int voltage = (int)evt->data;
        ESP_LOGW(TAG, "battery full %d", voltage);
    }
    else if (evt->type == BAT_SERV_EVENT_BAT_LOW)
    {
        int voltage = (int)evt->data;
        ESP_LOGE(TAG, "battery low %d", voltage);
    }
    else
    {
        ESP_LOGW(TAG, "unrecognized event %d", evt->type);
    }
    return ESP_OK;
}
